using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;
using XNAProjectLibrary;
using XNAProject.Core;
using XNAProject.Enumerations;
using XNAProject.Ships;


namespace XNAProject.GameElements
{
    public class PrepareStatePanel : Microsoft.Xna.Framework.DrawableGameComponent
    {
        SpriteFont font;
        Plane plane;

        Texture2D bottomPanel;
        Vector2 bottomPanelPosition;

        bool selected;
        float scale;
        int money;

        FleetLoader fleetLoader;

        Texture2D shipBackground;
        Texture2D[,] shipBackgroundCollection;
        Vector2[,] shipBackgroundPosition;
        Rectangle[,] shipBackgroundRectangle;
        Vector2 shipBackgroundSize;

        Texture2D loadButton;
        Vector2 loadButtonPosition;
        Rectangle loadButtonRectangle;

        #region ship

        Texture2D Cruiser;
        Model cruiserModel;

        Model shipModel; 
        Vector3 shipRotation;
        float shipScale;

        #endregion

        SaveFleet fleet;
        Level level;
        private IInputHandler Input;
        XNAGame OurGame;
        Player player;
        GameComponentCollection componentCollection;

        public PrepareStatePanel(Game game)
            : base(game)
        {
            OurGame = (XNAGame)game;
            level = (Level)Game.Services.GetService(typeof(Level));
            player = (Player)Game.Services.GetService(typeof(Player));
            componentCollection = (GameComponentCollection)game.Services.GetService(typeof(GameComponentCollection));
            GraphicsDeviceManager graphics = (GraphicsDeviceManager)Game.Services.GetService(typeof(GraphicsDeviceManager));
            Input = (IInputHandler)Game.Services.GetService(typeof(IInputHandler));

            fleet = new SaveFleet();
            fleetLoader = new FleetLoader(Game, ref fleet, this);
            selected = false;
            scale = 0.61f * graphics.PreferredBackBufferWidth / 1000;

            plane = new Plane(new Vector3(0f, 1f, 0f), 0f);
        }

        protected override void LoadContent()
        {
            font = Game.Content.Load<SpriteFont>(@"Fonts\description");

            bottomPanel = Game.Content.Load<Texture2D>("Textures/PrepareState/bottomPanel");
            shipBackground = Game.Content.Load<Texture2D>("Textures/FleetManager/shipBackground");
            bottomPanelPosition = new Vector2(Game.GraphicsDevice.Viewport.Width / 2 - bottomPanel.Width * scale / 2
                , Game.GraphicsDevice.Viewport.Height - (bottomPanel.Height * scale));

            loadButton = Game.Content.Load<Texture2D>("Textures/PrepareState/loadButton");
            loadButtonPosition = new Vector2(bottomPanelPosition.X + 800 * scale, bottomPanelPosition.Y + 17 * scale);
            loadButtonRectangle = new Rectangle((int)loadButtonPosition.X, (int)loadButtonPosition.Y, (int)(loadButton.Width * scale), (int)(loadButton.Height * scale));           

            shipBackgroundSize = new Vector2((int)Math.Truncate((bottomPanel.Width * scale) / (shipBackground.Width * scale)) - 1, 2);

            shipBackgroundPosition = new Vector2[(int)shipBackgroundSize.X, (int)shipBackgroundSize.Y];
            shipBackgroundRectangle = new Rectangle[(int)shipBackgroundSize.X, (int)shipBackgroundSize.Y];
            shipBackgroundCollection = new Texture2D[(int)shipBackgroundSize.X, (int)shipBackgroundSize.Y];

            for (int i = 0; i < shipBackgroundSize.X; i++)
            {
                for (int j = 0; j < shipBackgroundSize.Y; j++)
                {
                    shipBackgroundPosition[i, j] = new Vector2(bottomPanelPosition.X + i * shipBackground.Width * scale + 40,
                        bottomPanelPosition.Y + 60 + j * (shipBackground.Height + 10) * scale);

                    shipBackgroundCollection[i, j] = shipBackground;
                    shipBackgroundRectangle[i, j] = new Rectangle((int)shipBackgroundPosition[i, j].X, (int)shipBackgroundPosition[i, j].Y,
                        (int)(shipBackground.Width * 0.7f * scale), (int)(shipBackground.Height * 0.7f * scale));
                }
            }

            #region Ships

            Cruiser = Game.Content.Load<Texture2D>("Textures/FleetManager/cruiser");
            cruiserModel = Game.Content.Load<Model>("Models/Ships/Cruiser/Ship");

            #endregion         

            base.LoadContent();
        }

        public void LoadFleet()
        {
            player.ReSet();

            for (int i = 0; i < shipBackgroundSize.X; i++)
            {
                for (int j = 0; j < shipBackgroundSize.Y; j++)
                    shipBackgroundCollection[i, j] = shipBackground;

            }

            int p = 0;
            for (int i = 0; i < fleet.shipCollection.Count; i++)
            {
                if (i > shipBackgroundSize.X) p++;
                
                switch (fleet.shipCollection[i].name)
                {
                    case "Cruiser":
                        shipBackgroundCollection[i, p] = Cruiser;
                        break;
                    default:
                        shipBackgroundCollection[i, p] = shipBackground;
                        break;
                }
            }
        }

        public override void Update(GameTime gameTime)
        {
            if (Input.MouseLeftClicked())
            {
                if (!selected)
                {
                    for (int i = 0; i < shipBackgroundSize.X; i++)
                    {
                        for (int j = 0; j < shipBackgroundSize.Y; j++)
                        {
                            if (shipBackgroundRectangle[i, j].Intersects(new Rectangle(Input.MouseState.X, Input.MouseState.Y, 1, 1)))
                            {
                                if (shipBackgroundCollection[i, j] == Cruiser)
                                {
                                    shipModel = cruiserModel;
                                    shipRotation = new Vector3(0, 0, -0.05f);
                                    shipScale = 0.28f;
                                    shipBackgroundCollection[i, j] = shipBackground;
                                    selected = true;
                                }                                
                            }
                        }
                    }

                    if (loadButtonRectangle.Intersects(new Rectangle(Input.MouseState.X, Input.MouseState.Y, 1, 1)))
                    {
                        fleetLoader.Start();
                    }
                }
                else
                {
                    if (shipModel == cruiserModel)
                    {
                        Ship ship = new Cruiser(Game, ShipFaceing.Right, new Vector2((int)level.highlightedHexagon.X, (int)level.highlightedHexagon.Y));
                        player.AddShip(ship);
                        money += ship.cost;
                        componentCollection.Add(ship);
                        OurGame.Components.Add(ship);
                        selected = false;
                    }
                }
            }

            base.Update(gameTime);
        }

        public override void Draw(GameTime gameTime)
        {
            XNAProjectCamera camera = (XNAProjectCamera)Game.Services.GetService(typeof(XNAProjectCamera));

            OurGame.spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend);

            OurGame.spriteBatch.Draw(bottomPanel, bottomPanelPosition, null, Color.White, 0f, Vector2.Zero,
                scale, SpriteEffects.None, 0.1f);

            OurGame.spriteBatch.DrawString(font, (level.money - money).ToString(), new Vector2(bottomPanelPosition.X + 160 * scale, bottomPanelPosition.Y + 20 * scale),
                    Color.White, 0f, Vector2.Zero, scale * 1.5f, SpriteEffects.None, 0.2f);

            OurGame.spriteBatch.Draw(loadButton, loadButtonPosition, null, Color.White, 0f, Vector2.Zero,
                scale * 1.3f, SpriteEffects.None, 0.1f);

            for (int i = 0; i < shipBackgroundSize.X; i++)
            {
                for (int j = 0; j < shipBackgroundSize.Y; j++)
                {
                    OurGame.spriteBatch.Draw(shipBackgroundCollection[i, j], shipBackgroundPosition[i, j], null, Color.White, 0f, Vector2.Zero,
                            scale * 0.9f, SpriteEffects.None, 0.1f);
                }
            }

            if (selected)
            {
                double denominator = Vector3.Dot(plane.Normal, Input.CursorDirection(camera.Projection, camera.View));
                double numerator = Vector3.Dot(plane.Normal, Input.CursorRay(camera.Projection, camera.View).Position) + plane.D;
                double t = -(numerator / denominator);

                //a point on the hexagon plane
                Vector3 pickedPosition = Input.NearPoint(camera.Projection, camera.View) + Input.CursorDirection(camera.Projection, camera.View) * (float)t;

                Vector3 Translation = new Vector3(pickedPosition.X,
                    10f, pickedPosition.Z);

                foreach (ModelMesh mesh in shipModel.Meshes)
                {
                    foreach (BasicEffect effect in mesh.Effects)
                    {
                        effect.EnableDefaultLighting();
                        effect.PreferPerPixelLighting = true;

                        effect.World =
                            Matrix.CreateFromYawPitchRoll(shipRotation.X, shipRotation.Y, shipRotation.Z) *
                            Matrix.CreateScale(shipScale) *
                            Matrix.CreateTranslation(Translation);

                        effect.Projection = camera.Projection;
                        effect.View = camera.View;
                    }
                    mesh.Draw();
                }
            }

            OurGame.spriteBatch.End();

            base.Draw(gameTime);
        }
    }
}